package com.zws.cucumber.expr;

import com.zws.cucumber.var.ZwsVar;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
//import org.springframework.util.Base64Utils;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;

import static com.zws.cucumber.expr.ZwsExpr.registerTransformer;

/**
 * author: zws
 */
public class ZwsExprBuiltInTransformers {

    public static void init() {
        registerTransformer("format_txlog",
            ZwsExprBuiltInTransformers::transformByFormatTxlog);
        registerTransformer("url_enc",
            ZwsExprBuiltInTransformers::transformByUrlEncoding);
        registerTransformer("url_dec",
            ZwsExprBuiltInTransformers::transformByUrlDecoding);
        registerTransformer("base64_enc",
            ZwsExprBuiltInTransformers::transformByBase64Encoding);
        registerTransformer("base64_enc_url_safe",
            ZwsExprBuiltInTransformers::transformByBase64UrlSafeEncoding);
        registerTransformer("base64_dec",
            ZwsExprBuiltInTransformers::transformByBase64Decoding);
        registerTransformer("base64_dec_url_safe",
            ZwsExprBuiltInTransformers::transformByBase64UrlSafeDecoding);
        registerTransformer("save",
                ZwsExprBuiltInTransformers::save);
    }

    private static Pair<Object, Object> transformByFormatTxlog(List<String> args, String pattern, Object actual) {
        if (pattern == null) {
            return null;
        }
        String[] searchStrings = new String[] {",", "\"", "\r", "\n"};
        String[] replaceStrings = new String[] {";", "", "", ""};
        return Pair.of(StringUtils.replaceEach(pattern, searchStrings, replaceStrings), actual);
    }

    private static Pair<Object, Object> transformByUrlEncoding(List<String> args, String pattern, Object actual) {
        try {
            String result = URLEncoder.encode(pattern, StandardCharsets.UTF_8.name());
            return Pair.of(result, actual);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    private static Pair<Object, Object> transformByUrlDecoding(List<String> args, String pattern, Object actual) {
        try {
            String result = URLDecoder.decode(pattern, StandardCharsets.UTF_8.name());
            return Pair.of(result, actual);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    private static Pair<Object, Object> transformByBase64Encoding(List<String> args, String pattern, Object actual) {
//        String result = Base64Utils.encodeToString(pattern.getBytes(StandardCharsets.UTF_8));
        String result = Base64.getEncoder().encodeToString(pattern.getBytes(StandardCharsets.UTF_8));
        return Pair.of(result, actual);
    }

    private static Pair<Object, Object> transformByBase64UrlSafeEncoding(List<String> args, String pattern, Object actual) {
//        String result = Base64Utils.encodeToUrlSafeString(pattern.getBytes(StandardCharsets.UTF_8));
        String result = Base64.getUrlEncoder().encodeToString(pattern.getBytes(StandardCharsets.UTF_8));
        return Pair.of(result, actual);
    }

    private static Pair<Object, Object> transformByBase64Decoding(List<String> args, String pattern, Object actual) {
//        String result = new String(Base64Utils.decodeFromString(pattern), StandardCharsets.UTF_8);
        String result = new String(Base64.getDecoder().decode(pattern));
        return Pair.of(result, actual);
    }

    private static Pair<Object, Object> transformByBase64UrlSafeDecoding(List<String> args, String pattern, Object actual) {
//        String result = new String(Base64Utils.decodeFromUrlSafeString(pattern), StandardCharsets.UTF_8);
        String result = new String(Base64.getUrlDecoder().decode(pattern));
        return Pair.of(result, actual);
    }

    private static Pair<Object, Object> save(List<String> args, String pattern, Object actual) {
        String savedName = args.get(0);
        ZwsVar.put(savedName, actual);
        return Pair.of(pattern, actual);
    }

}
